
import json
import time
import asyncio
import sqlite3
import aiohttp
from aiohttp.web import Application, Response, View, json_response, run_app
from config import API_PORT, DB_ADDRESS

async def _fetch(url, client):
    async with client.get(url) as resp:
        assert resp.status == 200
        html = await resp.text()
        status = resp.status
        return {'response': html, 'status': status}


async def _request(url, loop):
    async with aiohttp.ClientSession(loop=loop) as client:
        return await _fetch(url, client)


def _conn_sqlite():
    return sqlite3.connect(DB_ADDRESS)


def _create_table():
    conn = _conn_sqlite()
    c = conn.cursor()
    c.execute("""
    CREATE TABLE proxys (ip, port, time)
    """)


def insert_data(sql):
    print(sql)
    conn = _conn_sqlite()
    conn.execute(sql)
    conn.commit()
    conn.close()


def select_data(sql):
    data_list = []
    conn = _conn_sqlite()
    c = conn.cursor()
    for data in c.execute(sql):
        data_list.append(data)
    c.close()
    conn.close()
    return data_list


async def fetch_proxy(loop):
    api_url = 'http://www.xdaili.cn/ipagent/privateProxy/applyStaticProxy?count=20&spiderId=a1bba778ab6845b2af2d6160c7176ee3&returnType=2'
    response = await _request(api_url, loop)
    json_proxy = json.loads(response['response'])
    if response.get('status') == 200 and json_proxy['ERRORCODE'] == '0':
        for ips in json_proxy['RESULT']:
            sql = "SELECT * FROM proxys WHERE ip = '{ip}'".format(ip=ips['ip'])
            try:
                select = select_data(sql)
            except sqlite3.OperationalError:
                _create_table()
                select = select_data(sql)
            if not select:
                ips['time'] = int(time.time())
                insert_sql = """INSERT INTO proxys (ip, port, time) VALUES(
                '{ip}', '{port}', '{time}')""".format(
                    ip=ips['ip'], port=ips['port'], time=ips['time']
                )
                insert_data(insert_sql)
            else:
                print(select)
                print('-------------------------------')
    else:
        raise ValueError('Request status Error :{}'.format(str(response)))


async def get_ips(request):
    data = {'test': '212121212121'}
    sql = '''
            SELECT ip, port, time
            FROM proxys
            WHERE time > '{}'
            '''.format(int(time.time()) - (4 * 60))
    proxy_data = select_data(sql)
    # proxy_data = select_data('SELECT ip, port, time FROM proxys')
    print(len(proxy_data))
    return json_response(proxy_data)


async def check_headers(request):
    print(request)
    print(request.headers)
    request_data = dict(request.headers)
    peername = request.transport.get_extra_info('peername')
    if peername is not None:
        host, port = peername
        request_data['request_ip'] = host
        request_data['request_port'] = port
        print(host)
        print(port)
        print('----- request ip -----')
    for k, v in request.headers.items():
        print(k, v)
    from pprint import pprint
    # pprint(dir(request))
    data = {'test': '212121212121'}
    return json_response(request_data)


async def init(loop):
    app = Application(loop=loop)
    app.router.add_get('/', get_ips)
    app.router.add_get('/headers', check_headers)
    return app


async def test(loop):
    start_time = 0
    i_time = 10.1
    sleep_time = 0.1
    while True:
        if (time.time() - start_time) >= i_time:
            try:
                await fetch_proxy(loop)
                start_time = time.time()
                if sleep_time != 0.1:
                    sleep_time = 0.1

            except Exception as e:
                sleep_time = 1
                print(e)
        else:
            await asyncio.sleep(sleep_time)


def main():
    try:
        _create_table()
    except sqlite3.OperationalError:
        pass
    loop = asyncio.get_event_loop()
    loop.create_task(test(loop))
    app = loop.run_until_complete(init(loop))
    run_app(app, port=API_PORT)


if __name__ == '__main__':
    main()
